unit cuSimpleArrays;

interface

{
  Created by: Daniel Mark Avis

  A simple class which can store an array of integers,
}

uses  SysUtils,
      cuDebug, cuSplitLine, cuFuncs;

type
  TIntegerArray = class( TObject )
  private
    m_Count       : integer;
    m_Items       : array of integer;
    m_arrayName   : string;
    m_nextItemID  : integer;
    m_addedValue  : integer;
  public
    constructor Create(newArrayName:string);
    destructor Destroy(); override;
    procedure clearArray(onEvent:string);
    function addItem(newValue:integer):boolean;
    function getItem(theIndex:integer):integer;
    function setItem(theIndex,theValue:integer):boolean;
    function quickDelete(deleteIndex:integer):boolean;        // returns true if delete successful
//    function Delete(deleteIndex:integer):boolean;        // returns true if delete successful
    function DeleteByValue(deleteValue:integer):boolean; // locates an array index which holds a certain value and deletes that index.
    function find(findValue:integer):integer;            // tries to find a array item with the Value, returns -1 if fails.
    function getNextItem():boolean;
    function currentItem():integer;

    procedure fillArray(minValue,maxValue:integer);
    procedure setArrayValues(theValues:string);
    function exportValues():string;

    property addedValue : integer read m_addedvalue;
    property Count : integer read m_Count;
  end;
  TStringArray  = array of string;
  TRealArray    = array of real;

implementation

{
  Create
}
constructor TIntegerArray.Create(newArrayName:string);
begin
  inherited Create();

  m_arrayName := newArrayName;
  ClearArray('create');
end;

{
  Destroy
}
destructor TIntegerArray.Destroy();
begin
  ClearArray('destroy');

  inherited;
end;

{
  clearArray
}
procedure TIntegerArray.clearArray(onEvent:string);
begin
  DevConsole.Print(LOG_DEBUG3, 'TIntArray.clearArray: ('+m_arrayName+') Clearing Array ( '+onEvent+' )');

  m_Count := 0;
  SetLength( m_Items, m_Count );

  m_addedValue := 0;
  m_nextItemID := -1;
end;

{
  addItem
}
function TIntegerArray.addItem(newValue:integer):boolean;
begin
  Inc( m_Count );
  SetLength( m_Items, m_Count );
  m_Items[ m_Count-1 ] := newValue;

  Inc( m_addedValue, newValue );

  DevConsole.Print(LOG_DEBUG3, 'TIntArray.Add: ('+m_arrayName+') Using ID #'+IntToStr(m_Count-1)+', add value #'+IntToStr(newValue));
  result := TRUE;
end;

{
  getItem
}
function TIntegerArray.getItem(theIndex:integer):integer;
begin
  result := -1;

  if (InRange(theIndex, 0, m_Count-1)) then
    result := m_Items[theIndex];
end;

{
  setItem
}
function TIntegerArray.setItem(theIndex,theValue:integer):boolean;
begin
  result := false;

  if (InRange(theIndex, 0, m_Count-1)) then
  begin
    m_Items[theIndex] := theValue;
    result := TRUE;
  end;
end;

{
  Delete
}
function TIntegerArray.quickDelete(deleteIndex:integer):boolean;
begin
  result := FALSE;

  if (not inRange( deleteIndex, 0, m_Count-1 )) then
  begin
    DevConsole.Print( LOG_CRITICAL, '(TIntArray.delete / '+m_arrayName+') Index out of bounds #'+IntToStr(deleteIndex)+' (High #'+IntToStr(m_Count-1)+') :: Error Output >>> '+exportValues() );
    DevConsole.saveLog();
    exit;
  end;

  DevConsole.Print(LOG_DEBUG3, '(TIntArray.delete / '+m_arrayName+') deleting index #'+IntToStr(deleteIndex));

  Dec( m_addedValue, m_Items[deleteIndex] );

  m_Items[deleteIndex] := m_Items[ m_Count-1 ]; // Move the last object to the deleteing index, faster than moving all indexs down one.

  dec( m_Count );
  SetLength(m_Items, m_Count ); //reduce the array by one.

  result := TRUE;
end;

{
  DeleteByValue
}
function TIntegerArray.DeleteByValue(deleteValue:integer):boolean;
var index:integer;
begin
  index := Find( deleteValue );

  result := quickDelete( index );
end;

{
  Find
}
function TIntegerArray.Find(findValue:integer):integer; // Finds the index number, which holds the required number.
var I : integer;
begin
  result := -1;
  for I := 0 to m_Count-1 do
  begin
    if (m_Items[I] = findValue) then
    begin
      result := I;
      exit;
    end;
  end;
end;

{
  getNextItem
}
function TIntegerArray.getNextItem():boolean;
begin
  result := FALSE;

  if (m_nextItemID >= m_Count-1) then
  begin
    m_nextItemID := -1; //Reset this ready for the next line (if exist), nearly missed this...
    exit;
  end;

  result := TRUE;

  Inc( m_nextItemID );
end;

{
  currentItem
}
function TIntegerArray.currentItem():integer;
begin
  if (m_nextItemID > -1) then
    result := m_Items[ m_nextItemID ]
  else
    result := -1;
end;

{
  fillArray
}
procedure TIntegerArray.fillArray(minValue,maxValue:integer); //Fills an array of "min" to "max", and fills it with its own index value as an integer.
var A : integer;
begin
  if (m_Count > 0) then
    ClearArray('fillArray');

  DevConsole.Print(LOG_DEBUG3, 'TIntArray.fillArray: ('+m_arrayName+') Filling the Array');

  for A := minValue to maxValue do
    addItem( A );
end;

{
  setArrayValues
}
procedure TIntegerArray.setArrayValues(theValues:string);
var SplitLine:TSplitLine;
begin
  if (m_Count > 0) then
    ClearArray('setArrayValues');

  DevConsole.Print(LOG_DEBUG3, 'TIntArray.setArrayValues ('+m_arrayName+') Setting Array Values from "'+theValues+'"');

  SplitLine := TSplitLine.Create();
  SplitLine.explodeString( theValues );

  while SplitLine.getNextWord() do
  begin
    addItem( SplitLine.toInt(SplitLine.NextWordID) );
  end;

  FreeAndNil( SplitLine );
end;

{
  exportValues
}
function TIntegerArray.exportValues():string;
var I : integer;
begin
  for I := 0 to m_Count-1 do
    result := result + IntToStr(m_Items[I])+', ';
end;

end.
